package com.liu.core;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.liu.configuration.CustomObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.exceptions.JedisException;

import javax.annotation.Resource;
import java.util.Set;

/**
 * @ClassName RedisTemplate
 * @Author liuxin
 * @Date Created in 2023-01-12 20:59
 * @Version 1.0
 */
@Component
@Slf4j
public class RedisTemplate {

    @Resource
    private JedisPool jedisPool;

    @Resource
    private CustomObjectMapper objectMapper;


    /**
     * 这里是用来保存字符串类型数据，redis的set（key，value）的方法
     */

    public String set(String key, String value, Long expire) {
        Jedis jedis = jedisPool.getResource();

        String returnValue = null;
        //这个是一设置过期时间的方法,而且这个有可能有一个异常
        try {
            returnValue = jedis.setex(key, expire, value);
        } catch (JedisException jedisException) {
            log.error("redis execution error!", jedisException);
            jedisPool.returnBrokenResource(jedis);
        } finally {
            //无论如何都需要将资源还回池子
            jedisPool.returnResource(jedis);
        }

        return returnValue;
    }

    public String get(String key) {
        Jedis jedis = jedisPool.getResource();

        String returnValue = null;
        //这个是一设置过期时间的方法,而且这个有可能有一个异常
        try {
            returnValue = jedis.get(key);
        } catch (JedisException jedisException) {
            log.error("redis execution error!", jedisException);
            jedisPool.returnBrokenResource(jedis);
        } finally {
            //无论如何都需要将资源还回池子
            jedisPool.returnResource(jedis);
        }

        return returnValue;
    }

    /**
     * 将对象以序列化的方式存在redis当中
     */


    public String setObject(String key, Object value, Long expire) {
        Jedis jedis = jedisPool.getResource();

        String returnValue = null;
        //这个是一设置过期时间的方法,而且这个有可能有一个异常
        try {
            //先序列化成json
            String jsonValue = objectMapper.writeValueAsString(value);
            //因为setex不能输入负数的时间，也就是永久，set可以输入，这里手动对expire进行一次判断
            if (expire < 0) {
                returnValue = jedis.set(key, jsonValue);
            } else {
                returnValue = jedis.setex(key, expire, jsonValue);
            }

        } catch (JedisException | JsonProcessingException exception) {
            log.error("redis execution error!", exception);
            jedisPool.returnBrokenResource(jedis);
        } finally {
            //无论如何都需要将资源还回池子
            jedisPool.returnResource(jedis);
        }

        return returnValue;
    }

    //    public <T> T getObject(String key, Class<T> clazz){

    public <T> T getObject(String key, TypeReference<T> typeReference) {
        Jedis jedis = jedisPool.getResource();
        T object = null;
        String returnValue = null;
        //这个是一设置过期时间的方法,而且这个有可能有一个异常
        try {
            //从redis中获取
            returnValue = jedis.get(key);
            //object = objectMapper.readValue(returnValue, clazz);
            object = objectMapper.readValue(returnValue, typeReference);
        } catch (JedisException | JsonProcessingException exception) {
            log.error("redis execution error!", exception);
            jedisPool.returnBrokenResource(jedis);
        } finally {
            //无论如何都需要将资源还回池子
            jedisPool.returnResource(jedis);
        }
        return object;
    }

    /**
     * 输入key可以写成可变参数
     */

    public Long remove(String ...key) {
        Jedis jedis = jedisPool.getResource();

        long del =0L;
        String returnValue = null;
        //这个是一设置过期时间的方法,而且这个有可能有一个异常
        try {
            del = jedis.del(key);
        } catch (JedisException jedisException) {
            log.error("redis execution error!", jedisException);
            jedisPool.returnBrokenResource(jedis);
        } finally {
            //无论如何都需要将资源还回池子
            jedisPool.returnResource(jedis);
        }

        return del;
    }
    //增加key的时间
    public long  expire(String key, Long expire) {
        Jedis jedis = jedisPool.getResource();
        Long exp = -1L;
        //这个是一设置过期时间的方法,而且这个有可能有一个异常
        try {
            //从redis中设置过期时间完成token续命
            exp = jedis.expire(key,expire);

        } catch (JedisException  exception) {
            log.error("redis execution error!", exception);
            jedisPool.returnBrokenResource(jedis);
        } finally {
            //无论如何都需要将资源还回池子
            jedisPool.returnResource(jedis);
        }
        return exp;
    }

    //查询特定key，pattern是条件，返回特定条件的key全部查询并返回

    public Set<String> keys(String pattern) {
        Jedis jedis = jedisPool.getResource();
        Set<String> keys=null;
        //这个是一设置过期时间的方法,而且这个有可能有一个异常
        try {
            //从redis中设置过期时间完成token续命
            keys = jedis.keys(pattern);

        } catch (JedisException  exception) {
            log.error("redis execution error!", exception);
            jedisPool.returnBrokenResource(jedis);
        } finally {
            //无论如何都需要将资源还回池子
            jedisPool.returnResource(jedis);
        }
        return keys;
    }

}
